/// \file		WnAcceptor.h
/// \brief		WIND监听接收类的声明文件
/// \author		xuefeng
/// \version	1.0
/// \date		2011-07-19
/// \history	2011-07-19 新建
#pragma once

#include "WnAcceptorBase.h"
#include "WnConnection.h"
#include <string>
#include <boost/asio/io_service.hpp>

/// \brief WIND监听接收类
template<typename Protocol>
class WnAcceptor : public WnAcceptorBase, public boost::enable_shared_from_this<WnAcceptor<Protocol> >
{
public:
  typedef typename Protocol::acceptor acceptor_type;
  typedef typename Protocol::endpoint endpoint_type;
  typedef typename Protocol::resolver resolver_type;

  /// \brief 构造函数
  /// \param apEndPoint 本地终端
  /// \param oIoService IO异步处理服务
  WnAcceptor(END_POINT_APTR apEndPoint, boost::asio::io_service& oIoService)
    : WnAcceptorBase(apEndPoint)
    , m_io_service(oIoService)
    , m_oAcceptor(oIoService)
    , m_oListenEndpoint()
    , m_oResolver(oIoService)
    , m_apNewConnection()
  {}

  virtual ~WnAcceptor(void)
  {
    writeLock lock(m_mtx_apNewConnection);
    m_apNewConnection.reset();
  }

  /// \brief 设定终端地址
  /// \param strHostName 主机名
  /// \param strPort 端口号
  int SetAddr(const std::string& strHostName, const std::string& strPort);

  /// \brief 启动监听
  /// \return 成功与否
  bool Start();

  /// \brief 停止监听
  void Stop();

private:
  /// \brief 启动监听的实际执行函数
  /// \return 成功与否
  bool StartListen();

  /// \brief 接受连接
  void BeginAccept();

  /// \brief 接受后处理函数
  void HandleAccept(const boost::system::error_code& oErrorCode);

private:
  boost::asio::io_service& m_io_service;
  // 接收器
  acceptor_type m_oAcceptor;

  // 监听端口
  endpoint_type m_oListenEndpoint;

  // 分解器
  resolver_type m_oResolver;

  // 最新的连接
  CONNECTION_APTR m_apNewConnection;
  boost::shared_mutex m_mtx_apNewConnection;
};

template<typename Protocol>
int WnAcceptor<Protocol>::SetAddr(const std::string& strHostName, const std::string& strPort)
{
  int nResult = 0;
  typename resolver_type::query oQuery(strHostName, strPort);
  typename boost::system::error_code oErrorCode = boost::asio::error::host_not_found;

  typename resolver_type::iterator itEndpoint = m_oResolver.resolve(oQuery, oErrorCode);
  if(oErrorCode)
    nResult = oErrorCode.value();
  else
    m_oListenEndpoint = *itEndpoint;
  return nResult;
}

template<typename Protocol>
bool WnAcceptor<Protocol>::Start()
{
  boost::mutex::scoped_lock lock(m_oRunningMutex);
  bool blResult = true;
  if(!m_blRunning)
  {
    m_blRunning = true;
    blResult = StartListen();
    if(!blResult)
      m_blRunning = false;
  }
  return blResult;
}

template<typename Protocol>
void WnAcceptor<Protocol>::Stop()
{
  {
    boost::mutex::scoped_lock lock(m_oRunningMutex);
    m_blRunning = false;
    m_oAcceptor.close();
  }

  {
    writeLock lock(m_mtx_apNewConnection);
    m_apNewConnection.reset();
  }
}

template<typename Protocol>
bool WnAcceptor<Protocol>::StartListen()
{
  bool blResult = true;
  do
  {
    try
    {
      m_oAcceptor.open(m_oListenEndpoint.protocol());
      typename acceptor_type::reuse_address op(true);
      m_oAcceptor.set_option(op);
      m_oAcceptor.bind(m_oListenEndpoint);
      m_oAcceptor.listen();
    }
    catch(std::exception& ec)
    {
      {
        stringstream ss;
        ss << "file:" << __FILE__ << ", function:" << __FUNCTION__ << ", line:" << __LINE__ << ". @@@. "
          << "服务端创建监听器失败. info:" << ec.what();
        if(m_apLocalEndPoint)
          m_apLocalEndPoint->OnMsg(2, ss.str());
      }
      blResult = false;
      break;
    }
    catch(...)
    {
      {
        stringstream ss;
        ss << "file:" << __FILE__ << ", function:" << __FUNCTION__ << ", line:" << __LINE__ << ". @@@. "
          << "服务端创建监听器失败. info:" << "未知";
        if(m_apLocalEndPoint)
          m_apLocalEndPoint->OnMsg(2, ss.str());
      }
	  blResult = false;
      break;
    }

    BeginAccept();
  }
  while(false);
  return blResult;
}

template<typename Protocol>
void WnAcceptor<Protocol>::BeginAccept()
{
  WnConnection<Protocol>* poConnection = new WnConnection<Protocol>(m_apLocalEndPoint, m_io_service);
  {
    writeLock lock(m_mtx_apNewConnection);
    m_apNewConnection.reset(poConnection);
  }
  m_oAcceptor.async_accept(poConnection->GetSocket(), boost::bind(&WnAcceptor<Protocol>::HandleAccept, shared_from_this(), boost::asio::placeholders::error));
}

// 如果被回调，代表有新的客户端连接
template<typename Protocol>
void WnAcceptor<Protocol>::HandleAccept(const boost::system::error_code& oErrorCode)
{
  boost::mutex::scoped_lock lock(m_oRunningMutex);
  if(m_blRunning)
  {
    if(!oErrorCode)
    {
      {
        readLock lock(m_mtx_apNewConnection);
        m_apNewConnection->OnAccept();
      }
      BeginAccept();
    }
    else
    {
      {
        stringstream ss;
        ss << "file:" << __FILE__ << ", function:" << __FUNCTION__ << ", line:" << __LINE__ << ". @@@. "
          << "HandleAccept处理异常. info:" << oErrorCode.message();
        if(m_apLocalEndPoint)
          m_apLocalEndPoint->OnMsg(2, ss.str());
      }

      m_oAcceptor.close();
      StartListen();
    }
  }
}
